home *** CD-ROM | disk | FTP | other *** search
Text File | 1989-08-06 | 7.2 KB | 251 lines | [TEXT/PJMM] |
- unit PinUpMain;
- {--This is the source code of the PinUpMenu XFCN--}
- {--Written by Steven Fuchs--}
- {--PO Box 129, Coram, NY 11727--}
-
- interface
- uses
- XCMDIntF, XCMDUtils;
- procedure MAIN (ParamPtr: XCMDPtr);
- implementation
- type
- MenuArray = array[0..15] of MenuHandle;
- StrArray = array[0..15] of str255;
-
- procedure MAIN (ParamPtr: XCMDPtr);
- var
- TheMenus: MenuArray;
- TheParams: StrArray;
- PinUpWindow: WindowPtr;
- OldPort: GrafPtr;
- EndRect: rect;
- Name, TheAnswer: str255;
- item: longint;
-
-
- {---HandleDrawing is a simple routine to draw our windows string---}
- procedure HandleDrawing;
- begin
- MoveTo(PinUpWindow^.portrect.left + 2, PinUpWindow^.portrect.bottom - 4);
- DrawString(Name);
- end;
-
- {---HandleThisUpdate determines the correct action to take in response---}
- {---to an Update Event, if the window is ours it calls HandleDrawing, if---}
- {---it is the Hypercard main window, it calls SendCardMessage, otherwise---}
- {---(most likely one of the tool pallettes) it removes the message---}
- procedure HandleThisUpdate (LilWindow: WindowPtr);
- begin
- BeginUpdate(LilWindow);
- if WindowPtr(LilWindow) = OldPort then
- SendCardMessage(ParamPtr, 'Go to this card')
- else if WindowPtr(LilWindow) = PinUpWindow then
- HandleDrawing
- else
- ValidRect(LilWindow^.portrect);
- EndUpdate(LilWindow);
- end;
-
- {---GetParams is responsible for transferring the parameters---}
- {---sent to MAIN into our variables: Name, and the TheParams arrray}
- function GetParams: boolean;
- var
- NumOfMenus, z: integer;
- begin
- NumOfMenus := ParamPtr^.ParamCount - 1;
- GetParams := NumOfMenus >= 1;
- ZeroToPas(ParamPtr, ParamPtr^.params[1]^, Name);
- for z := 1 to 15 do
- if z <= NumOfMenus then
- begin
- ZeroToPas(ParamPtr, ParamPtr^.params[z + 1]^, TheParams[z]);
- TheParams[z] := Include(',', TheParams[z], length(TheParams[z]) + 1);
- end
- else
- TheParams[z] := '';
- end;
-
- {---ReturnWindowRect must determine the length of the string “Name”---}
- {---Size the rectangle so the string fits nicely inside, and locate it so that---}
- {---it appears in the same spot regardless of screen size---}
- procedure ComputeWindowRect;
- var
- DummyPt: point;
- begin
- SetPt(DummyPt, 150, 100);
- SetRect(EndRect, 0, 0, stringwidth(Name) + 20, 17);
- LocaltoGlobal(DummyPt);
- OffsetRect(EndRect, DummyPt.h, DummyPt.v);
- end;
-
- {---CreateWindow does just that, creating the window for us and setting up---}
- {--the default drawing characteristics---}
- procedure CreateWindow;
- var
- LongOne: LongInt;
- begin
- PinUpWindow := NewWindow(nil, EndRect, 'The Course', false, 3, nil, false, LongOne);
- SetPort(PinUpWindow);
- TextFont(0);
- TextSize(12);
- ShowWindow(PinUpWindow);
- SelectWindow(PinUpWindow);
- end;
-
- {---HitCameInWindow holds our event loop, where it waits for a mousedown---}
- {---if this mousedown is within the window we return true, otherwise false.---}
- function HitCameInWindow: boolean;
- var
- Event: EventRecord;
- begin
- HitCameInWindow := false;
- repeat
- SystemTask;
- if GetNextEvent(EveryEvent, Event) then
- case Event.What of
- MouseDown:
- if PtInRect(Event.Where, EndRect) then
- HitCameInWindow := true;
- UpdateEvt:
- HandleThisUpdate(WindowPtr(event.message));
- ActivateEvt:
- HandleDrawing;
- otherwise
- end
- until Event.What = Mousedown;
- end;
-
- {---ReturnAndMaul is our parsing function, it reads the first item from---}
- {---the string indicated by Index and returns it. It then deletes that item---}
- function ReturnAndMaul (Index: integer): str255;
- var
- ThePlace: integer;
- begin
- ThePlace := Pos(',', TheParams[Index]);
- if ThePlace = 0 then
- ReturnAndMaul := ''
- else
- begin
- ReturnAndMaul := str255(copy(TheParams[Index], 1, ThePlace - 1));
- delete(TheParams[Index], 1, ThePlace);
- end;
- end;
-
- {---CreateSubMenu does just that, creating the menu with NewMenu and---}
- {---sets the correct fields in the main menu to indicate the submenu exists---}
- procedure CreateSubMenu (Index: integer);
- var
- swf, saf: char;
- begin
- swf := chr($1B);
- saf := chr(240 + Index);
- TheMenus[Index] := NewMenu(240 + Index, 'ASubMenu');
- {--Tell Mac OS we have a submenu--}
- SetItemCmd(TheMenus[0], Index, swf);
- {--Tell Mac OS which Menu it is--}
- SetItemMark(TheMenus[0], Index, saf);
- end;
-
- {---AddAllItems calls ReturnAndMaul repeatedly until there is nothing---}
- {---left of the string indicated by Index. Each of the items up until---}
- {---that point is appended to the end of the submenu.---}
- procedure AddAllItems (TIndex: integer);
- var
- stripe: str255;
- x: integer;
- begin
- repeat
- stripe := ReturnAndMaul(TIndex);
- if stripe <> '' then
- AppendMenu(TheMenus[TIndex], Stripe);
- until stripe = '';
- {--Insert our menu into hierarchical portion of MenuList--}
- InsertMenu(TheMenus[TIndex], -1);
- end;
-
- {---BuildThoseMenus is the top layer, it creates the main menu and adds the---}
- {---items, decides if that item needs submenus and if so calls the procedures---}
- {---to add them---}
- procedure BuildThoseMenus;
- var
- Increment: integer;
- ScaredStr: str255;
- begin
- TheMenus[0] := NewMenu(240, 'MainMenu');
- for increment := 1 to 15 do
- begin
- TheMenus[increment] := nil;
- ScaredStr := ReturnAndMaul(increment);
- if ScaredStr <> '' then
- begin
- AppendMenu(TheMenus[0], ScaredStr);
- if Pos(',', TheParams[increment]) <> 0 then
- begin
- CreateSubMenu(increment);
- AddAllItems(increment);
- end;
- end;
- end;
- {--Insert main menu into PopUp portion of Menu List--}
- {--Same call as for hierarchical menus--}
- InsertMenu(TheMenus[0], -1);
- end;
-
- {---ConvertAnswer takes the longint returned from PopUpMenuSelect and---}
- {--Converts it to the proper string for return to Hypercard---}
- function ConvertAnswer (TheL: longInt): str255;
- var
- ThePrimary, TheSecondary: str255;
- begin
- if TheL = 0 then
- ConvertAnswer := 'Cancel'
- else if HiWord(TheL) = 240 then
- begin
- GetItem(TheMenus[HiWord(TheL) - 240], LoWord(TheL), TheSecondary);
- ConvertAnswer := TheSecondary;
- end
- else
- begin
- GetItem(TheMenus[0], HiWord(TheL) - 240, ThePrimary);
- GetItem(TheMenus[HiWord(TheL) - 240], LoWord(TheL), TheSecondary);
- ConvertAnswer := Str255(concat(ThePrimary, ',', TheSecondary))
- end;
- end;
-
- {--CleanUpMess takes care of the very important work of cleaning up the---}
- {---heap before handing the reins back to Hypercard---}
- procedure CleanUpMess;
- var
- x: integer;
- begin
- DisposeWindow(PinUpWindow);
- for x := 0 to 15 do
- if TheMenus[x] <> nil then
- begin
- DeleteMenu(240 + x);
- DisposeMenu(TheMenus[x]);
- end;
- end;
-
-
- {---Here is the code for the procedure MAIN, it acts at the highest level---}
- {--farming out almost all of the tasks to its other procedures and functions---}
- begin
- GetPort(OldPort);
- TheAnswer := 'Cancel';
- if GetParams then
- begin
- ComputeWindowRect;
- CreateWindow;
- BuildThoseMenus;
- if HitCameInWindow then
- begin
- Item := PopUpMenuSelect(TheMenus[0], EndRect.bottom + 4, EndRect.left, 0);
- TheAnswer := ConvertAnswer(Item);
- end;
- SetPort(OldPort);
- CleanUpMess;
- end;
- ParamPtr^.returnvalue := PastoZero(ParamPtr, TheAnswer);
- end;
- end.